/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.persistence.hibernate.mapping.type;

import java.io.Serializable;

import org.hibernate.usertype.UserType;
import org.springframework.util.ObjectUtils;

/**
 * This abstract class is a base class for all immutable {@link UserType}.
 */
public abstract class AbstractImmutableUserType
    implements UserType
{

  /**
   * Reconstruct an object from the cacheable representation. At the very least
   * this method should perform a deep copy if the type is mutable. (optional
   * operation)
   * 
   * @param cached
   *          the object to be cached
   * @param owner
   *          the owner of the cached object
   * @return a reconstructed object from the cachable representation
   */
  public Object assemble(Serializable cached, Object owner)
  {
    return cached;
  }



  /**
   * Return a deep copy of the persistent state, stopping at entities and at
   * collections. It is not necessary to copy immutable objects, or null values,
   * in which case it is safe to simply return the argument.
   * 
   * @param value
   *          the object to be cloned, which may be null
   * @return Object a copy
   */
  public Object deepCopy(Object value)
  {
    return value;
  }



  /**
   * Transform the object into its cacheable representation. At the very least
   * this method should perform a deep copy if the type is mutable. That may not
   * be enough for some implementations, however; for example, associations must
   * be cached as identifier values. (optional operation)
   * 
   * @param value
   *          the object to be cached
   * @return a cachable representation of the object
   */
  public Serializable disassemble(Object value)
  {
    return (Serializable) value;
  }



  /**
   * Compare two instances of the class mapped by this type for persistence
   * "equality". Equality of the persistent state.
   * 
   * @param object1
   *          the first object to compare
   * @param object2
   *          the second object to compare
   * @return <code>true</code> if the 2 objects are equals, <code>false</code>
   *         otherwise
   */
  public boolean equals(Object object1, Object object2)
  {
    return ObjectUtils.nullSafeEquals(object1, object2);
  }



  /**
   * Get a hashcode for the instance, consistent with persistence "equality".
   * 
   * @param object
   *          the object to hash
   * @return the hashcode
   * @see org.hibernate.usertype.UserType#hashCode(java.lang.Object)
   */
  public int hashCode(Object object)
  {
    return object.hashCode();
  }



  /**
   * Are objects of this type mutable?
   * 
   * @return boolean
   */
  public boolean isMutable()
  {
    return false;
  }



  /**
   * During merge, replace the existing (target) value in the entity we are
   * merging to with a new (original) value from the detached entity we are
   * merging. For immutable objects, or null values, it is safe to simply return
   * the first parameter. For mutable objects, it is safe to return a copy of
   * the first parameter. For objects with component values, it might make sense
   * to recursively replace component values.
   * 
   * @param original
   *          the value from the detached entity being merged
   * @param target
   *          the value in the managed entity
   * @param owner
   *          the owner of the cached object
   * @return the value to be merged
   * @see org.hibernate.usertype.UserType#replace(java.lang.Object,
   *      java.lang.Object, java.lang.Object)
   */
  public Object replace(Object original, Object target, Object owner)
  {
    return original;
  }

}
